﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Trade.Library.Cache
{
    using System.Reflection;
    using System.Web.Caching;

    /// <summary>
    /// 缓存接口
    /// </summary>
    public interface ICache
    {

        /// <summary>
        /// 判断指定名称的cache对象是否存在
        /// </summary>
        /// <param name="cacheName">cache对象名称</param>
        /// <returns></returns>
        bool HasCache(string cacheName);

        /// <summary>
        /// 从 System.Web.Caching.Cache 对象检索指定项。
        /// </summary>
        /// <param name="cacheName">要检索的缓存项的标识符。</param>
        /// <returns>检索到的缓存项，未找到该键时为 null。</returns>
        object GetCache(string cacheName);

        /// <summary>
        /// 获取或设置指定键处的缓存项
        /// </summary>
        /// <param name="key">表示缓存项的键的 System.String 对象。</param>
        /// <returns>指定的缓存项。</returns>
        object this[string key] { get; set; }

        /// <summary>
        /// 从 System.Web.Caching.Cache 对象检索所有项。
        /// </summary>
        /// <returns></returns>
        Dictionary<string, object> GetAllCache();

        /// <summary>
        /// 从应用程序的 Cache 对象移除指定项。
        /// </summary>
        /// <param name="cacheName"></param>
        /// <returns></returns>
        object RemoveCache(string cacheName);

        /// <summary>
        /// 从应用程序的 Cache 对象移除所有项。
        /// </summary>
        /// <returns></returns>
        Dictionary<string, object> RemoveAllCache();

        /// <summary>
        /// 获取存储在缓存中的项数
        /// </summary>
        int Count { get; }

        /// <summary>
        /// 将指定项添加到 System.Web.Caching.Cache 对象，该对象具有依赖项、到期和优先级策略以及一个委托（可用于在从 Cache 移除插入项时通知应用程序）。
        /// </summary>
        /// <param name="key">用于引用该项的缓存键。</param>
        /// <param name="value">要添加到缓存的项。</param>
        /// <param name="dependencies">该项的文件依赖项或缓存键依赖项。当任何依赖项更改时，该对象即无效，并从缓存中移除。如果没有依赖项，则此参数包含 null。</param>
        /// <param name="absoluteExpiration">所添加对象将到期并被从缓存中移除的时间。如果使用可调到期，则 absoluteExpiration 参数必须为 System.Web.Caching.Cache.NoAbsoluteExpiration。</param>
        /// <param name="slidingExpiration">最后一次访问所添加对象时与该对象到期时之间的时间间隔。如果该值等效于 20 分钟，则对象在最后一次被访问 20 分钟之后将到期并从缓存中移除。如果使用绝对到期，则slidingExpiration 参数必须为 System.Web.Caching.Cache.NoSlidingExpiration。</param>
        /// <param name="priority">对象的相对成本，由 System.Web.Caching.CacheItemPriority 枚举表示。缓存在退出对象时使用该值；具有较低成本的对象在具有较高成本的对象之前被从缓存移除。</param>
        /// <param name="onRemoveCallback">在从缓存中移除对象时所调用的委托（如果提供）。当从缓存中删除应用程序的对象时，可使用它来通知应用程序。</param>
        /// <returns>如果该项先前存储在 Cache 中，则为 System.Object，否则为 null。</returns>
        object AddCache(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback);

        //
        // 摘要:
        //     检索用于循环访问包含在缓存中的键设置及其值的字典枚举数。
        //
        // 返回结果:
        //     要循环访问 System.Web.Caching.Cache 对象的枚举数。
        //public IDictionaryEnumerator GetEnumerator();

        /// <summary>
        /// 向 System.Web.Caching.Cache 对象插入项，该项带有一个缓存键引用其位置，并使用 System.Web.Caching.CacheItemPriority枚举提供的默认值。
        /// </summary>
        /// <param name="key">用于引用该项的缓存键。</param>
        /// <param name="value">要插入缓存中的对象。</param>
        void InsertCache(string key, object value);

        /// <summary>
        /// 向 System.Web.Caching.Cache 中插入具有文件依赖项或键依赖项的对象。
        /// </summary>
        /// <param name="key">用于标识该项的缓存键。</param>
        /// <param name="value">要插入缓存中的对象。</param>
        /// <param name="dependencies">所插入对象的文件依赖项或缓存键依赖项。当任何依赖项更改时，该对象即无效，并从缓存中移除。如果没有依赖项，则此参数包含 null。</param>
        void InsertCache(string key, object value, CacheDependency dependencies);

        /// <summary>
        /// 向 System.Web.Caching.Cache 中插入具有依赖项和到期策略的对象。
        /// </summary>
        /// <param name="key">用于引用该对象的缓存键。</param>
        /// <param name="value">要插入缓存中的对象。</param>
        /// <param name="dependencies">所插入对象的文件依赖项或缓存键依赖项。当任何依赖项更改时，该对象即无效，并从缓存中移除。如果没有依赖项，则此参数包含 null。</param>
        /// <param name="absoluteExpiration">所插入对象将到期并被从缓存中移除的时间。要避免可能的本地时间问题（例如从标准时间改为夏时制），请使用 System.DateTime.UtcNow而不是 System.DateTime.Now 作为此参数值。如果使用绝对到期，则 slidingExpiration 参数必须为 System.Web.Caching.Cache.NoSlidingExpiration。</param>
        /// <param name="slidingExpiration">最后一次访问所插入对象时与该对象到期时之间的时间间隔。如果该值等效于 20 分钟，则对象在最后一次被访问 20 分钟之后将到期并被从缓存中移除。如果使用可调到期，则absoluteExpiration 参数必须为 System.Web.Caching.Cache.NoAbsoluteExpiration。</param>
        void InsertCache(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration);

        /// <summary>
        /// 将对象与依赖项策略、到期策略和优先级策略以及可用来在从缓存中移除项之前通知应用程序的委托一起插入到 System.Web.Caching.Cache对象中。
        /// </summary>
        /// <param name="key">用于引用对象的缓存键。</param>
        /// <param name="value">要插入到缓存中的对象。</param>
        /// <param name="dependencies">该项的文件依赖项或缓存键依赖项。当任何依赖项更改时，该对象即无效，并从缓存中移除。如果没有依赖项，则此参数包含 null。</param>
        /// <param name="absoluteExpiration">所插入对象将到期并被从缓存中移除的时间。要避免可能的本地时间问题（例如从标准时间改为夏时制），请使用 System.DateTime.UtcNow而不是 System.DateTime.Now 作为此参数值。如果使用绝对到期，则 slidingExpiration 参数必须设置为 System.Web.Caching.Cache.NoSlidingExpiration。</param>
        /// <param name="slidingExpiration"> 缓存对象的上次访问时间和对象的到期时间之间的时间间隔。如果该值等效于 20 分钟，则对象在最后一次被访问 20 分钟之后将到期并被从缓存中移除。如果使用可调到期，则absoluteExpiration 参数必须设置为 System.Web.Caching.Cache.NoAbsoluteExpiration。</param>
        /// <param name="onUpdateCallback">从缓存中移除对象之前将调用的委托。可以使用它来更新缓存项并确保缓存项不会从缓存中移除。</param>
        void InsertCache(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback);

        /// <summary>
        /// 向 System.Web.Caching.Cache 对象中插入对象，后者具有依赖项、到期和优先级策略以及一个委托（可用于在从 Cache 移除插入项时通知应用程序）。
        /// </summary>
        /// <param name="key">用于引用该对象的缓存键。</param>
        /// <param name="value">要插入缓存中的对象。</param>
        /// <param name="dependencies">该项的文件依赖项或缓存键依赖项。当任何依赖项更改时，该对象即无效，并从缓存中移除。如果没有依赖项，则此参数包含 null。</param>
        /// <param name="absoluteExpiration">所插入对象将到期并被从缓存中移除的时间。要避免可能的本地时间问题（例如从标准时间改为夏时制），请使用 System.DateTime.UtcNow而不是 System.DateTime.Now 作为此参数值。如果使用绝对到期，则 slidingExpiration 参数必须为 System.Web.Caching.Cache.NoSlidingExpiration。</param>
        /// <param name="slidingExpiration">最后一次访问所插入对象时与该对象到期时之间的时间间隔。如果该值等效于 20 分钟，则对象在最后一次被访问 20 分钟之后将到期并被从缓存中移除。如果使用可调到期，则absoluteExpiration 参数必须为 System.Web.Caching.Cache.NoAbsoluteExpiration。</param>
        /// <param name="priority">该对象相对于缓存中存储的其他项的成本，由 System.Web.Caching.CacheItemPriority 枚举表示。该值由缓存在退出对象时使用；具有较低成本的对象在具有较高成本的对象之前被从缓存移除。</param>
        /// <param name="onRemoveCallback">在从缓存中移除对象时将调用的委托（如果提供）。当从缓存中删除应用程序的对象时，可使用它来通知应用程序。</param>
        void InsertCache(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback);
    }

    /// <summary>
    /// 缓存及实例管理器
    /// </summary>
    public class CacheManager
    {

        /// <summary>
        /// 获取缓存的实现
        /// </summary>
        /// <param name="typename">实现的类名</param>
        /// <param name="assemblyName"></param>
        /// <returns></returns>
        public static ICache GetICache(string typename, string assemblyName)
        {
            var assembly = Assembly.Load(new AssemblyName(assemblyName));
            return (ICache)assembly.CreateInstance(typename);
        }

    }
}
